基础使用示例
本示例展示了VPage API的基本使用方法。
示例:用户管理页面
// 监听页面初始化事件
thisApp.pageOnInit = (context) => {
// 创建用户表单
const formBuilder = context.addForm();
// 创建搜索条件字段集合
const searchFieldSet = formBuilder.addFieldSet({
title: '搜索条件',
fieldsPerLine: 2
});
searchFieldSet
.addField({
id: 'search',
type: 'text',
title: '搜索关键词',
placeholder: '输入用户名或邮箱搜索'
})
.addField({
id: 'status',
type: 'select',
title: '状态',
options: [
{ label: '全部', value: '' },
{ label: '启用', value: 'active' },
{ label: '禁用', value: 'inactive' }
]
});
// 添加操作按钮
const actionBar = context.getActionBar();
actionBar.addButton({
id: 'search-btn',
text: '搜索',
title: '根据当前搜索条件执行搜索',
type: 'raised',
onClick: (formExecutionContext) => {
// 搜索逻辑
console.log('执行搜索');
}
});
actionBar.addButton({
id: 'add-user',
text: '新增用户',
title: '打开用户添加页面',
type: 'outline',
onClick: (formExecutionContext) => {
// 跳转到用户添加页面
console.log('打开用户添加页面');
}
});
};
// 监听页面激活事件
thisApp.pageOnActive = async (context) => {
// 获取页面上下文
const pageContext = context.getPageContext();
const params = pageContext.getQueryParams();
// 更新页面标题
pageContext.changeTitle(`用户管理 - ${params.department || '全部'}`);
// 加载用户列表数据
try {
const result = await pageContext.graphql(`
query {
users: User(criteriaStr: "department = ${params.department}") {
id
name
email
department
}
}
`);
console.log('用户数据加载完成:', result.users);
} catch (error) {
console.error('加载用户数据失败:', error);
}
};
// 监听页面取消激活事件
thisApp.pageOnDeActive = (context) => {
console.log('用户管理页面即将失去焦点');
// 可以在这里保存搜索条件等状态
};
示例:订单详情页面
thisApp.pageOnInit = (context) => {
const formBuilder = context.addForm();
// 创建订单详情表单
const orderFieldSet = formBuilder.addFieldSet({
title: '订单信息',
fieldsPerLine: 2
});
orderFieldSet
.addField({
id: 'orderNumber',
type: 'Text',
title: '订单编号',
readonly: true
})
.addField({
id: 'customerName',
type: 'Text',
title: '客户名称',
readonly: true
})
.addField({
id: 'totalAmount',
type: 'Amount',
title: '订单金额',
readonly: true
})
.addField({
id: 'status',
type: 'Select',
title: '订单状态',
options: [
{ label: '待处理', value: 'pending' },
{ label: '已确认', value: 'confirmed' },
{ label: '已发货', value: 'shipped' },
{ label: '已完成', value: 'completed' }
]
});
// 添加操作按钮
const actionBar = context.getActionBar();
actionBar.addButton({
id: 'confirm',
text: '确认订单',
title: '确认当前订单',
type: 'raised',
onClick: async (formExecutionContext) => {
// 确认订单逻辑
console.log('确认订单');
}
});
actionBar.addButton({
id: 'ship',
text: '发货',
title: '执行发货操作',
type: 'outline',
onClick: (formExecutionContext) => {
console.log('发货操作');
}
});
actionBar.addButton({
id: 'close',
text: '关闭',
title: '关闭当前页面',
type: 'flat',
onClick: (formExecutionContext) => {
const pageContext = context.getPageContext();
pageContext.closeTab();
}
});
};
thisApp.pageOnActive = async (context) => {
// 获取页面上下文
const pageContext = context.getPageContext();
const params = pageContext.getQueryParams();
if (params.orderId) {
try {
const result = await pageContext.graphql(`
query {
order :Order(criteriaStr: "id = ${params.orderId}") {
id
orderNumber
customerName
totalAmount
status
}
}
`);
// 填充表单数据
console.log('订单数据:', result.order);
pageContext.changeTitle(`订单详情 - ${result.order?.[0].orderNumber}`);
} catch (error) {
console.error('加载订单数据失败:', error);
}
}
};
示例:测试脚本
thisApp.pageOnActive = async (ctx) => {
console.log("页签激活")
}
thisApp.pageOnDeActive = async (ctx) => {
console.log("页签隐藏")
}
thisApp.pageOnInit = async (ctx) => {
const pageCtx = ctx.getCurrentContext();
const pageTitle = ctx.getPageContext().getTitle()
ctx.getPageContext().changeTitle("新增" + pageTitle)
const builder2 = pageCtx.addForm();
const block1 = builder2.addStackBlock({
direction: "row",
spacing: 10
})
const row1 = block1.addStackItem({
style: {
height: '150px'
}
})
const fieldSet = row1.addFieldSet({
title: "基础信息",
fieldsPerLine: 4
})
fieldSet.addField({
id: 'name',
title: '名称',
type: 'Text'
})
fieldSet.addField({
id: 'businessDate',
title: '业务日期',
type: 'Date'
})
fieldSet.addField({
id: 'project',
title: '项目',
type: 'EntityRef',
source: 'Project'
});
fieldSet.addField({
id: 'description',
title: '备注',
type: 'MultiText'
});
let num = 6
const row2 = block1.addStackItem({
style: {
height: 'calc(100vh - 310px)'
}
})
subGrid = row2.addSubTreeGrid({
id: "department",
title: "部门",
visible: false,
style: {
height: '100%'
},
parentIdFieldName: "parentId",
idFieldName: "id",
hasChildrenFieldName: "hasChildren"
})
subGrid.addField({
id: 'name',
title: '名称',
type: 'Text'
})
subGrid.addField({
id: 'id',
title: 'id',
type: 'Text',
readonly: true
})
subGrid.addField({
id: 'parentId',
title: 'parentId',
type: 'Text',
readonly: true
})
subGrid.addField({
id: 'hasChildren',
title: 'hasChildren',
type: 'Checkbox',
readonly: true,
hidden: true
})
subGrid.addField({
id: 'hasCategory',
title: 'hasCategory',
type: 'Checkbox',
readonly: true,
hidden: true
})
const block = row2.addStackBlock({
direction: "horizontal",
spacing: 10,
style: {
height: '100%'
},
})
const departmentData = [
{
id: 1,
name: "部门1",
hasChildren: true,
hasCategory: true
},
{
id: 2,
name: "部1-1",
parentId: 1,
hasChildren: false
},
{
id: 4,
name: "部1-2",
parentId: 1,
hasChildren: true,
hasCategory: false
},
{
id: 5,
name: "部1-2-1",
parentId: 4,
hasChildren: false
},
{
id: 3,
name: "部门3",
hasChildren: false
}
]
const column1 = block.addStackItem({
style: {
width: '25%',
height: '100%'
}
})
const subGrid1 = column1.addSubTreeGridView({
id: "category",
title: "部门分类",
refFieldName: "department",
wdith: 300,
parentIdFieldName: "parentId",
idFieldName: "id",
hasChildrenFieldName: "hasCategory",
actions: {
disable: true
},
style: {
height: '100%'
},
onRowSelectionChanged: (data) => {
console.log("选择部门", data)
const id = data[0] && data[0].id
builder2.getFormNode().getSubTreeGridView("departmentDisplay").setFilter((item) => {
let temp = builder2.getFormNode().getSubTreeGrid("department").value
if (id) {
temp = findNodeAndDescendants(builder2.getFormNode().getSubTreeGrid("department").value, id)
}
return item.id === id || temp.find(i => i.id === item.id)
})
}
})
subGrid1.changeRowSelection("single")
subGrid1.addField({
id: 'name',
title: '名称',
type: 'Text',
readonly: true,
width: 100
})
subGrid1.addField({
id: 'id',
title: 'id',
type: 'Text',
readonly: true,
})
// subGrid1.addField({
// id: 'parentId',
// title: 'parentId',
// type: 'Text',
// readonly: true,
// hidden: true
// })
// subGrid1.addField({
// id: 'hasChildren',
// title: 'hasChildren',
// type: 'Checkbox',
// readonly: true,
// hidden: true
// })
const column2 = block.addStackItem({
style: {
width: '75%',
height: '100%'
}
})
const tabs = column2.addTabs({
style: {
height: '100%'
}
})
subGrid2 = tabs.addSubTreeGridViewTab({
id: "departmentDisplay",
title: "部门展示",
refFieldName: "department",
style: {
height: '100%'
},
parentIdFieldName: "parentId",
idFieldName: "id",
hasChildrenFieldName: "hasChildren",
actions: {
customActions: [{
key: "add",
title: "添加下级",
onClick: function onClick(index, data) {
num += 1;
data.hasChildren = true;
data.hasCategory = true
qiqi.builder.createDialogFormBuilder()
builder2.getFormNode().getSubTreeGrid("department").appendChild(data.id, {
id: num
});
rebuildCategory()
}
},
{
key: "addToSameLevel",
title: "添加同级",
onClick: function onClick(index, data) {
num += 1;
builder2.getFormNode().getSubTreeGrid("department").appendChild(data.parentId, {
id: num
});
rebuildCategory()
}
},
{
key: "moveUp",
title: "移动到上级",
onClick: function onClick(index, data) {
num += 1;
parent = builder2.getFormNode().value.department.find(i => i.id === data.parentId)
if (parent) {
data.parentId = parent.parentId
} else {
data.parentId = ""
}
rebuildCategory()
}
}
]
}
})
subGrid2.addField({
id: 'name',
title: '名称',
type: 'Text'
})
subGrid2.addField({
id: 'id',
title: 'id',
type: 'Text',
readonly: true
})
subGrid2.addField({
id: 'parentId',
title: 'parentId',
type: 'Text',
readonly: true
})
subGrid2.addField({
id: 'hasChildren',
title: 'hasChildren',
type: 'Checkbox',
readonly: true,
hidden: true
})
const subGrid3 = tabs.addSubGridTab({
id: "projectList",
title: "项目明细",
style: {
height: '100%'
}
})
subGrid3.addField({
id: 'name',
title: '名称',
type: 'Text'
})
builder2.load({
formOnLoad: function formOnLoad(ctx) {
console.log("表单加载完成", ctx.getCurrentContext().form);
builder2.getFormNode().getSubTreeGridView("category").setFilter((item) => {
return isFirstTwoLevel(item)
})
},
value: {
code: "20250111",
department: departmentData
}
});
const actionBar = pageCtx.getActionBar()
actionBar.addButton({
text: "保存",
onClick: function () {
console.log("保存", builder2.getFormNode())
},
type: "raised"
});
actionBar.addButton({
text: "关闭",
onClick: function () {
ctx.getPageContext().closeTab()
}
})
function findNodeAndDescendants(data, targetId, idKey = 'id', parentIdKey = 'parentId') {
const result = [];
const visited = new Set(); // 避免重复处理
// 首先找到目标节点
const targetNode = data.find(item => item[idKey] === targetId);
if (!targetNode) {
return result;
}
// 添加目标节点
result.push(targetNode);
visited.add(targetNode[idKey]);
// 递归查找所有下级节点
function findDescendants(parentId) {
const children = data.filter(item =>
item[parentIdKey] === parentId && !visited.has(item[idKey])
);
for (const child of children) {
if (!visited.has(child[idKey])) {
result.push(child);
visited.add(child[idKey]);
findDescendants(child[idKey]);
}
}
}
// 从目标节点开始查找下级
findDescendants(targetId);
return result;
}
function isFirstTwoLevel(item, idField = 'id', parentIdField = 'parentId') {
const data = builder2.getFormNode().getSubTreeGrid("department").value
if (!Array.isArray(data) || data.length === 0) {
return false
}
// 第一级节点:没有parentId或parentId为null/undefined
if (!item[parentIdField]) {
return true
}
const parent = data.find(i => i.id === item[parentIdField])
if (!parent || !parent[parentIdField]) {
return true
}
return false
}
const rebuildCategory = () => {
const data = builder2.getFormNode().getSubTreeGrid("department").value
data.forEach(i => {
if (!i.parentId) {
i.hasCategory = !!data.find(item => item.parentId === i.id)
return
}
i.hasCategory = false
})
}
}